iT邦幫忙

2026 iThome 鐵人賽

DAY 27
1
Modern Web

Three.js × WebGL 實戰:打造 HD-2D 像素地下城與即時光影系統系列 第 27 篇

Day 27:立體感的靈魂!Three.js 即時光學架構如何賦予 2D 平面「三維體積」

  • 分享至 

  • xImage
  •  

在 Day 26 中,我們解析了透視平截頭體、三維物理視差與 Z-Buffer 空間錨定,成功讓 2D 像素圖片在三維空間中建立了正確的幾何深度與遮擋關係。

然而,當幾何架構搭建完成後,許多初入 WebGL 領域的開發者會立刻撞上第二堵視覺高牆:「為什麼畫面看起來依然生硬死板,像是一堆廉價的灰色 3D 模型上,貼了幾張浮空的彩色紙片?」

這正是「幾何空間」與「真實視覺」之間的落差所在。在現實世界中,人類並不是靠幾何座標來感受深度的,而是靠光子在物體表面的反彈、衰減、漸變與陰影來辨識物體的厚度與材質。

今天我們將聚焦於本專案的另一大靈魂支柱——即時光學系統(Real-Time Lighting Architecture),深入探討 Three.js 如何透過冷暖三層光源模型、接觸陰影物理錨定,以及著色器光學乘積,把平面的 2D 貼紙雕刻出厚重扎實的三維體積!

一、三層光學金字塔:用冷暖色溫雕刻空間層次

在 Web 3D 場景中,最常見的錯誤就是「隨便放一顆全域白光,把整個場景均勻照亮」。這種照明方式會抹平所有物體的明暗交界線,直接扼殺空間感。

在專案中,我們設計了一套「冷暖互補的三層光學模型」,從微觀到宏觀層層鎖定光學秩序:
image

環境底色層:幽深夜藍,消滅「物理死黑」

如果場景中沒有環境光,所有照不到光線的背光面都會直接掉進 rgb(0, 0, 0) 的純黑深淵中。這在真實物理中是不存在的,因為大氣與地面永遠存在漫反射光。

  • 光學設定:我們採用帶有冷調青灰藍的環境光底色(Ambient / Hemisphere Light)。
  • 功能:它為整座地宮提供了一層微弱的暗部能見度,讓石磚背光面依然隱約可見細微刻痕,為後續的主光源留出足夠的動態範圍(Dynamic Range)。

結構雕刻層:高角度斜射月光,界定 3D 幾何立面

單有環境光,場景只是一片灰藍。我們在天頂架設了一道高角度斜射的平行光(DirectionalLight,模擬穿透地宮殘垣的冷白月光):

  • 法線明暗對比(Normal Shading):光線從斜上方 45 度射下時,水平向上的「地面石磚」接收到最高光通量而變亮;而垂直向下的「牆壁側立面」因夾角變大而變暗。

  • 長條幾何投影:石牆與殘壁在地面上投射出清晰的長條影子,精準交代了「這堵牆到底有多高」、「這根柱子立在哪裡」。

核心動態層:1850K 暖金火把,創造視覺焦點與冷暖張力

前兩層光全是「冷色調」,營造出古堡遺跡幽深、潮濕且荒涼的基調。
而主角手中的隨身火把(PointLight),則採用了 1850K 黑體輻射的暖金琥珀色:

  • 冷暖對比(Temperature Contrast):暖金色的局部火光與廣袤的冷藍夜色在螢幕上形成強烈的色彩張力,玩家的視線在瞬間被牢牢鎖定在角色周圍。
  • 物理衰減落差:火把光線採用 $1.85$ 次方衰減,光芒從中心的高亮明金向外擴散,平滑融入深藍夜色中,將通道深處的黑暗襯托得更加深邃。

二、接觸陰影(Contact Shadow):消滅漂浮感的物理膠水

在 3D 遊戲開發中,有一個極其頑固的視覺痛點:紙片人角色看起來永遠像「浮在半空中」。

為什麼角色會漂浮?

人類大腦判斷一個物體「是否真正接觸地面」的唯一視覺依據,就是觀察物體底部與地面的接觸陰影(Ambient Occlusion / Contact Shadow)。

  • 3D 模型有厚度,模型底部的多邊形與地面重疊時能產生自然的自遮擋。

  • 但 2D 精靈圖是一張垂直的紙片,它與地面的接觸面在幾何上只有「一條厚度為 0 的線」!如果只靠全域陰影貼圖,微弱的偏差就會讓角色與影子脫節,產生詭異的浮空感。

物理膠水:專屬貼地高斯接觸面片

為了給紙片人注入實體重量感,我們在角色的腳底正下方(y = 1.02,剛好略高於地面石磚 y = 1.0 以防止 Z-Fighting 深度衝突),放置了一塊專屬的圓形接觸陰影面片:

// 角色貼地接觸陰影 (物理膠水)
const shadowGeo = new THREE.PlaneGeometry(1.2, 0.6);
const shadowMat = new THREE.MeshBasicMaterial({
  map: createSoftShadowTexture(), // 核心由黑向外漸變的高斯軟邊貼圖
  transparent: true,
  opacity: 0.6,
  depthWrite: false               // 禁止寫入深度緩衝,避免阻礙角色本身的遮擋渲染
});

const footShadow = new THREE.Mesh(shadowGeo, shadowMat);
footShadow.rotation.x = -Math.PI / 2; // 水平躺平成為地面陰影
playerGroup.add(footShadow);
  • 橢圓形扁平幾何:考慮到 28 度的俯視透視相機角度,正圓形的陰影在螢幕上會變形。我們採用長寬比 $1.2 : 0.6$ 的扁橢圓形,在相機投影後剛好呈現自然的受壓散焦感。

  • 高斯核心衰減:陰影貼圖中心為純黑高濃度、向外平滑漸變至透明。

  • 視覺心理學效應:當角色的足跡與這片緊貼地面的軟陰影完全重合時,大腦會瞬間產生「這是一個具備數十公斤重量的實體角色踏在石板上」的強烈錯覺,浮空感徹底消散!

三、著色器光學乘積:把 2D 貼紙雕刻成立體圓柱體

如果 2D 紙片人始終保持貼圖原色,那麼無論周圍的光影多麼華麗,角色依然像一張浮在動態背景上的「發光色塊」。

Three.js 原生的 SpriteMaterial 是不參與場景光照計算的(Unlit)。為了解決這個斷層,我們在 Day 20 透過 onBeforeCompile 在片段著色器中實現了「動態受光乘積」:
image

這行乘積背後蘊藏著極為精妙的圖形學構想:

告別平面:將四邊形虛擬化為「3D 圓柱體」

一張 2D 面片在數學上是平的,它的表面法線永遠筆直朝向攝影機。如果直接拿面片法線去算光照,整張圖會呈現死板的「整張變亮」或「整張變暗」。我們在著色器中利用精靈圖的橫向局部座標($vLocalX \in [0.0, 1.0]$),在像素著色階段人工虛擬出了一個微曲面的圓弧法線:

  • 靠近火把的那一側(迎光面):賦予高光通量與暖金反射色(warmLight)。

  • 背向火把的那一側(背光面):平滑衰減為周圍環境的清冷月藍色(coolShadow)。

  • 中間過渡(smoothstep):模擬人體身軀圓柱體的幾何弧度,形成細膩的明暗交界線。

光影乘積的自然融合力

在著色器底層,當我們把貼圖原色乘上這個動態光學係數時:

  • 主角衣服的像素原本是綠色,在迎光側被染上一層薄薄的暖金晨曦感;

  • 在背光側,綠色則自然沉降為深暗且帶有些許藍調的冷暗綠;

  • 當火把隨著三諧波演算法產生呼吸律動時,角色身上的暖光也同步起伏。

2D 紙片人在這一刻不再是一張獨立的圖片,而是與整個 3D 空間的光子進行著即時的光學能量交換。

四、光線的空間衰減:界定可見世界的安全邊界

即時光影不僅負責「照亮」,在 HD-2D 的地宮氛圍中,光影更重要的任務是「定義未知的邊界」。

平方反比衰減帶來的幽閉縱深

在專案中,我們嚴格校準了火把的照射半徑(distance = 18)與衰減指數(decay = 1.85):

  • 中心高照度區(半徑 0 ~ 4 單位):角色的踏步、手中的木杖與腳下的石磚細節分明,帶給玩家強烈的安全感。

  • 過渡半影區(半徑 4 ~ 12 單位):光線能量呈非線性快速崩落,遠處的石柱在光影交界處若隱若現,牆面裂痕拉出長長的傾斜黑影。

  • 未知深邃區(半徑 12 單位以上):光線完全消逝在深藍色的環境霧氣中,將地宮深處的幽暗留給玩家的想像力。

這種明確的光線作用範圍,讓 3D 空間擁有了「近處清晰聚焦、遠處神秘隱沒」的呼吸節奏,為後續的後處理管線打下了完美的明暗基礎。

今天我們揭開了賦予平面 2D 資源「三維體積」的光學密碼:

  • 三層光學模型:以環境底色防死黑、高角度月光刻立面、暖金火把鎖焦點,構建具備冷暖對比的空間秩序。

  • 接觸陰影膠水:以貼地扁橢圓高斯軟邊面片,填補紙片人無體積的物理缺陷,徹底消除漂浮感。

  • 著色器曲面受光:在 GLSL 片段階段將 2D 平面虛擬為 3D 圓柱體,藉由動態光影乘積讓紙片人融入場景。

  • 非線性衰減界限:透過光線在空間中的崩落,勾勒出地宮由明入暗的幽閉縱深。

【本日結語】

現在,幾何透視有了,立體光學也有了。但如果直接將畫面輸出到螢幕上,它依然帶有一種現代 3D 軟體的「數位生硬感」。如何將這份數位畫面打碎,轉化為帶有微縮模型玩具感與膠卷質感的電影級畫面?

在下一篇 Day 28 中,我們將剖析最後的視覺魔法——打碎數位生硬感!後處理管線(Post-Processing)與鏡頭光學模擬!我們將深入推導自研的 TiltShiftVignetteShader 移軸景深、高斯卷積散景,以及 UnrealBloomPass 的極限高門檻漫射光暈!


上一篇
Day 26:空間維度轉換!用純 2D 資源在 WebGL 建立「3D 深度錯覺」的透視法則
下一篇
Day 28:打碎數位生硬感!後處理管線(Post-Processing)與鏡頭光學模擬:移軸景深、暗角與輝光解密
系列文
Three.js × WebGL 實戰:打造 HD-2D 像素地下城與即時光影系統 共 30 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

1
godlichen
iT邦新手 5 級 ‧ 2026-10-12 00:33:07

期待明天的文
!!!

我要留言

立即登入留言